/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.rpc.func;

import com.alibaba.fastjson2.JSON;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.func.funcPerm.ControlFieldAuthVo;
import com.je.common.base.func.funcPerm.FieldAuth.FieldAuthVo;
import com.je.common.base.func.funcPerm.dictionaryAuth.DictionaryAuthVo;
import com.je.common.base.func.funcPerm.fastAuth.FastAuthVo;
import com.je.common.base.func.funcPerm.fastAuth.FuncQuickPermission;
import com.je.common.base.func.funcPerm.roleSqlAuth.RoleSqlAuthVo;
import com.je.common.base.service.MetaService;
import com.je.common.base.util.SecurityUserHolder;
import com.je.common.base.util.StringUtil;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.cache.funcperm.*;
import com.je.meta.constant.FuncDataPermCons;
import com.je.meta.util.DataPermUtils;
import org.apache.servicecomb.provider.pojo.RpcSchema;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;

@RpcSchema(schemaId = "metaFuncPermService")
public class MetaFuncPermServiceImpl implements MetaFuncPermService {

    @Autowired
    private FastAuthCache fastAuthCache;
    @Autowired
    private DictionaryAuthCache dictionaryAuthCache;
    @Autowired
    private FieldAuthCache fieldAuthCache;
    @Autowired
    private RoleSqlAuthCache roleSqlAuthCache;
    @Autowired
    private SqlAuthCache sqlAuthCache;
    @Autowired
    private ControlFieldCache controlFieldCache;
    @Autowired
    private MetaService metaService;

    @Override
    public void restoreDefault(String funcCode) {
        String currentTenantId = SecurityUserHolder.getCurrentAccountTenantId();
        if (Strings.isNullOrEmpty(currentTenantId)) {
            fastAuthCache.removeCache(funcCode);
            fieldAuthCache.removeCache(funcCode);
            dictionaryAuthCache.removeCache(funcCode);
            roleSqlAuthCache.removeCache(funcCode);
            sqlAuthCache.removeCache(funcCode);
            controlFieldCache.removeCache(funcCode);
        } else {
            fastAuthCache.removeCache(currentTenantId, funcCode);
            fieldAuthCache.removeCache(currentTenantId, funcCode);
            dictionaryAuthCache.removeCache(currentTenantId, funcCode);
            roleSqlAuthCache.removeCache(currentTenantId, funcCode);
            sqlAuthCache.removeCache(currentTenantId, funcCode);
            controlFieldCache.removeCache(currentTenantId, funcCode);
        }
    }

    @Override
    public void putRedisCache(String funcCode, String type) {
        Object obj = getDataFromDB(funcCode, type);
        if (obj == null) {
            return;
        }

        String currentTenantId = SecurityUserHolder.getCurrentAccountTenantId();
        if (FuncDataPermCons.FAST_AUTH.equals(type)) {
            FastAuthVo fastAuthVo = (FastAuthVo) obj;
            if (Strings.isNullOrEmpty(currentTenantId)) {
                fastAuthCache.putCache(funcCode, fastAuthVo);
            } else {
                fastAuthCache.putCache(currentTenantId, funcCode, fastAuthVo);
            }
        }

        if (FuncDataPermCons.FIELD_AUTH.equals(type)) {
            FieldAuthVo fieldAuthVo = (FieldAuthVo) obj;
            if (Strings.isNullOrEmpty(currentTenantId)) {
                fieldAuthCache.putCache(funcCode, fieldAuthVo);
            } else {
                fieldAuthCache.putCache(currentTenantId, funcCode, fieldAuthVo);
            }
        }

        if (FuncDataPermCons.DICTIONARY_AUTH.equals(type)) {
            DictionaryAuthVo dictionaryAuthVo = (DictionaryAuthVo) obj;
            if (Strings.isNullOrEmpty(currentTenantId)) {
                dictionaryAuthCache.putCache(funcCode, dictionaryAuthVo);
            } else {
                dictionaryAuthCache.putCache(currentTenantId, funcCode, dictionaryAuthVo);
            }
        }

        if (FuncDataPermCons.ROLESQL_AUTH.equals(type)) {
            RoleSqlAuthVo roleSqlAuthVo = (RoleSqlAuthVo) obj;
            if (Strings.isNullOrEmpty(currentTenantId)) {
                roleSqlAuthCache.putCache(funcCode, roleSqlAuthVo);
            } else {
                roleSqlAuthCache.putCache(currentTenantId, funcCode, roleSqlAuthVo);
            }
        }

        if (FuncDataPermCons.SQL_AUTH.equals(type)) {
            String sqlAuth = (String) obj;
            if (Strings.isNullOrEmpty(sqlAuth)) {
                sqlAuthCache.putCache(funcCode, sqlAuth);
            } else {
                sqlAuthCache.putCache(currentTenantId, funcCode, sqlAuth);
            }
        }

        if (FuncDataPermCons.CONTROL_FIELD.equals(type)) {
            ControlFieldAuthVo controlFieldAuthVo = (ControlFieldAuthVo) obj;
            if (Strings.isNullOrEmpty(currentTenantId)) {
                controlFieldCache.putCache(funcCode, controlFieldAuthVo);
            } else {
                controlFieldCache.putCache(currentTenantId, funcCode, controlFieldAuthVo);
            }
        }

    }

    @Override
    public FastAuthVo getFastAuth(String funcCode) {
        String currentTenantId = SecurityUserHolder.getCurrentAccountTenantId();
        FastAuthVo fastAuthVo;
        if (Strings.isNullOrEmpty(currentTenantId)) {
            fastAuthVo = fastAuthCache.getCacheValue(funcCode);
        } else {
            fastAuthVo = fastAuthCache.getCacheValue(currentTenantId, funcCode);
        }

        if (fastAuthVo != null) {
            return fastAuthVo;
        }

        fastAuthVo = (FastAuthVo) getDataFromDB(funcCode, FuncDataPermCons.FAST_AUTH);
        if (fastAuthVo != null) {
            if (Strings.isNullOrEmpty(currentTenantId)) {
                fastAuthCache.putCache(funcCode, fastAuthVo);
            } else {
                fastAuthCache.putCache(currentTenantId, funcCode, fastAuthVo);
            }
        }

        return fastAuthVo;
    }

    @Override
    public FieldAuthVo getFiledAuth(String funcCode) {
        String currentTenantId = SecurityUserHolder.getCurrentAccountTenantId();
        FieldAuthVo fieldAuthVo;
        if (Strings.isNullOrEmpty(currentTenantId)) {
            fieldAuthVo = fieldAuthCache.getCacheValue(funcCode);
        } else {
            fieldAuthVo = fieldAuthCache.getCacheValue(currentTenantId, funcCode);
        }

        if (fieldAuthVo != null) {
            return fieldAuthVo;
        }

        fieldAuthVo = (FieldAuthVo) getDataFromDB(funcCode, FuncDataPermCons.FIELD_AUTH);
        if (fieldAuthVo != null) {
            if (Strings.isNullOrEmpty(currentTenantId)) {
                fieldAuthCache.putCache(funcCode, fieldAuthVo);
            } else {
                fieldAuthCache.putCache(currentTenantId, funcCode, fieldAuthVo);
            }
        }

        return fieldAuthVo;
    }

    @Override
    public RoleSqlAuthVo getRoleSqlAuth(String funcCode) {
        String currentTenantId = SecurityUserHolder.getCurrentAccountTenantId();
        RoleSqlAuthVo roleSqlAuthVo;
        if (Strings.isNullOrEmpty(currentTenantId)) {
            roleSqlAuthVo = roleSqlAuthCache.getCacheValue(funcCode);
        } else {
            roleSqlAuthVo = roleSqlAuthCache.getCacheValue(currentTenantId, funcCode);
        }

        if (roleSqlAuthVo != null) {
            return roleSqlAuthVo;
        }

        roleSqlAuthVo = (RoleSqlAuthVo) getDataFromDB(funcCode, FuncDataPermCons.ROLESQL_AUTH);
        if (roleSqlAuthVo != null) {
            if (Strings.isNullOrEmpty(currentTenantId)) {
                roleSqlAuthCache.putCache(funcCode, roleSqlAuthVo);
            } else {
                roleSqlAuthCache.putCache(currentTenantId, funcCode, roleSqlAuthVo);
            }
        }

        return roleSqlAuthVo;
    }

    @Override
    public String getSqlAuth(String funcCode) {
        String currentTenantId = SecurityUserHolder.getCurrentAccountTenantId();
        String sql;
        if (Strings.isNullOrEmpty(currentTenantId)) {
            sql = sqlAuthCache.getCacheValue(funcCode);
        } else {
            sql = sqlAuthCache.getCacheValue(currentTenantId, funcCode);
        }

        if (!Strings.isNullOrEmpty(sql)) {
            return sql;
        }

        sql = (String) getDataFromDB(funcCode, FuncDataPermCons.SQL_AUTH);
        if (StringUtil.isNotEmpty(sql)) {
            if (Strings.isNullOrEmpty(currentTenantId)) {
                sqlAuthCache.putCache(funcCode, sql);
            } else {
                sqlAuthCache.putCache(currentTenantId, funcCode, sql);
            }
        }

        return sql;
    }

    @Override
    public ControlFieldAuthVo controlField(String funcCode) {
        String currentTenantId = SecurityUserHolder.getCurrentAccountTenantId();
        ControlFieldAuthVo controlFieldAuthVo;
        if (Strings.isNullOrEmpty(currentTenantId)) {
            controlFieldAuthVo = controlFieldCache.getCacheValue(funcCode);
        } else {
            controlFieldAuthVo = controlFieldCache.getCacheValue(currentTenantId, funcCode);
        }

        if (controlFieldAuthVo != null) {
            return controlFieldAuthVo;
        }

        controlFieldAuthVo = (ControlFieldAuthVo) getDataFromDB(funcCode, FuncDataPermCons.CONTROL_FIELD);
        if (controlFieldAuthVo != null) {
            if (Strings.isNullOrEmpty(currentTenantId)) {
                controlFieldCache.putCache(funcCode, controlFieldAuthVo);
            } else {
                controlFieldCache.putCache(currentTenantId, funcCode, controlFieldAuthVo);
            }
        }

        return controlFieldAuthVo;
    }

    @Override
    public FuncQuickPermission getFuncQuickPermission(String funcCode) {
        FastAuthVo fastAuthVo = getFastAuth(funcCode);
        ControlFieldAuthVo controlFieldAuthVo = controlField(funcCode);
        if (fastAuthVo != null) {
            return DataPermUtils.toFuncQuickPermission(fastAuthVo, controlFieldAuthVo);
        }
        return null;
    }


    @Override
    public DictionaryAuthVo getDictionaryAuth(String funcCode) {
        String currentTenantId = SecurityUserHolder.getCurrentAccountTenantId();
        DictionaryAuthVo dictionaryAuthVo;
        if (Strings.isNullOrEmpty(currentTenantId)) {
            dictionaryAuthVo = dictionaryAuthCache.getCacheValue(funcCode);
        } else {
            dictionaryAuthVo = dictionaryAuthCache.getCacheValue(currentTenantId, funcCode);
        }

        if (dictionaryAuthVo != null) {
            return dictionaryAuthVo;
        }

        dictionaryAuthVo = (DictionaryAuthVo) getDataFromDB(funcCode, FuncDataPermCons.DICTIONARY_AUTH);
        if (dictionaryAuthVo != null) {
            if (Strings.isNullOrEmpty(currentTenantId)) {
                dictionaryAuthCache.putCache(funcCode, dictionaryAuthVo);
            } else {
                dictionaryAuthCache.putCache(currentTenantId, funcCode, dictionaryAuthVo);
            }
        }

        return dictionaryAuthVo;
    }

    private Object getDataFromDB(String funcCode, String type) {
        DynaBean dynaBean = metaService.selectOne("JE_CORE_FUNCPERM", ConditionsWrapper.builder()
                .eq("FUNCPERM_FUNCINFO_CODE", funcCode)
                .eq("FUNCPERM_TYPE", type));
        List<DynaBean> list = null;
        if (dynaBean != null) {
            String FUNCPERM_ON_OFF = dynaBean.getStr("FUNCPERM_ON_OFF");
            if (FuncDataPermCons.SQL_AUTH.equals(type)) {
                return dynaBean.get("FUNCPERM_CONFIG") == null ? "" : dynaBean.get("FUNCPERM_CONFIG");
            }
            if (FuncDataPermCons.CONTROL_FIELD.equals(type)) {
                ControlFieldAuthVo controlFieldAuthVo = JSON.parseObject(dynaBean.getStr("FUNCPERM_CONFIG"), ControlFieldAuthVo.class);
                return controlFieldAuthVo;
            }
            if (FuncDataPermCons.FAST_AUTH.equals(type)) {
                FastAuthVo fastAuthVo = JSON.parseObject(dynaBean.getStr("FUNCPERM_CONFIG"), FastAuthVo.class);
                fastAuthVo.setAuthOnOff(FUNCPERM_ON_OFF);
                return fastAuthVo;
            }
            list = metaService.select("JE_CORE_FUNCPERM_CONFIG", ConditionsWrapper.builder().eq("CONFIG_FUNCPERM_ID", dynaBean.getStr("JE_CORE_FUNCPERM_ID")));

            if (FuncDataPermCons.DICTIONARY_AUTH.equals(type)) {
                return DataPermUtils.toDictionaryAuthVo(FUNCPERM_ON_OFF, list);
            }
            if (FuncDataPermCons.FIELD_AUTH.equals(type)) {
                return DataPermUtils.toFieldAuthVo(FUNCPERM_ON_OFF, list);
            }

            if (FuncDataPermCons.ROLESQL_AUTH.equals(type)) {
                return DataPermUtils.toRoleSqlAuth(FUNCPERM_ON_OFF, list);
            }
        }
        return null;
    }
}
